package com.zhouyu.fileSync.FSclient;

import com.zhouyu.fileSync.FSclient.InvocationHandlers.RpcInvocationHandler;
import com.zhouyu.fileSync.FSclient.entities.ClientConfigs;
import com.zhouyu.fileSync.FSclient.registerClient.RegisterClient;
import com.zhouyu.fileSync.FSclient.registerClient.RegisterServiceRPCImpl;
import com.zhouyu.fileSync.FSclient.transmission.communicationBetweenClients.client.CommunicationClientCenter;
import com.zhouyu.fileSync.FSclient.transmission.communicationBetweenClients.server.CommunicationServer;
import com.zhouyu.fileSync.FScommon.api.RegisterServiceRPC;
import com.zhouyu.fileSync.FScommon.commonUtils.ConfigReader;
import com.zhouyu.fileSync.FScommon.entities.FSClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by zhouyu74748585@hotmail.com on 2019/9/2
 * the client main enter
 **/
public class ClientAppContext {

    static Logger logger = LogManager.getLogger(ClientAppContext.class);
    public static ClientConfigs CONFIGS;
    public static RegisterClient REGISTER_CLIENT;
    public static RegisterServiceRPC REGISTER_SERVICE_RPC;
    public static CommunicationClientCenter TRANSMISSION_JOB_CENTER;
    public static ConcurrentHashMap<String,FSClient> TARGETS=new ConcurrentHashMap<>();

    public static void main(String[] args) throws Exception {
        initConfig(ClientAppContext.class.getClassLoader().getResource("clientConfig.yml").getPath());
        startRegisterClient();
        connectToTheRegisterServer();
        getTargetClient();
        startTransmissionServer();
        TRANSMISSION_JOB_CENTER=new CommunicationClientCenter();
    }

    private static void initConfig(String filePath) throws IOException {
        CONFIGS = ConfigReader.readConfigs(filePath, ClientConfigs.class);
    }

    private static void startRegisterClient(){
        String host = CONFIGS.SERVER.getHost();
        int port = CONFIGS.SERVER.getPort();
        REGISTER_CLIENT = new RegisterClient(host,port);
        Thread registerThread=new Thread(REGISTER_CLIENT);
        registerThread.start();
    }

    private static void connectToTheRegisterServer() throws Exception {
        int count=0;
        boolean flag=true;
        while(flag) {
            if (REGISTER_CLIENT.getChannel()!=null&&REGISTER_CLIENT.getChannel().isWritable()) {
                REGISTER_SERVICE_RPC = (RegisterServiceRPC) new RpcInvocationHandler().newProxyInstance(new RegisterServiceRPCImpl(), REGISTER_CLIENT);
                REGISTER_SERVICE_RPC.registerClient(CONFIGS.CLIENT);
                flag=false;
            }else {
                count++;
                if (count == 10) {
                    throw new Exception("Failed to connect to the register server");
                }
                logger.info("Attempt to connect to the register server for the " + count + "th time");
                Thread.sleep(1000);
            }
        }
    }

    private static void getTargetClient(){
        for (FSClient target : CONFIGS.TARGETS) {
            //先尝试获取客户端,如果没有获取到,则等待要使用时再次尝试
            FSClient fsc=REGISTER_SERVICE_RPC.getClient(target.getClientName(),target.getClientPassword());
            if (fsc!=null) {
                TARGETS.put(target.getClientName(), fsc);
            }
        }
    }
    private static void startTransmissionServer(){
        CommunicationServer transmissionServer=new CommunicationServer();
        Thread transmissionServerThead=new Thread(transmissionServer);
        transmissionServerThead.start();
    }

}
